<?php

namespace app\common\service\student;

use app\common\enums\AccountTypeEnum;
use app\common\enums\ClassHourBusinessTypeEnum;
use app\common\enums\ClassHourStatusEnum;
use app\common\enums\core\PayTypeEnum;
use app\common\enums\UserConstantsEnum;
use app\common\model\banxi\core\CoreAccountClassHour;
use app\common\model\banxi\core\CoreClassHourDetail;
use app\common\model\banxi\organization\Organization;
use app\common\model\banxi\organization\OrganizationLevelConfig;
use app\common\model\banxi\student\Student;
use app\common\service\ApiService;
use app\common\service\ConfigService;
use app\common\service\pay\AlipayService;
use app\common\service\pay\WxPayService;
use app\common\service\qrcode\QrcodeService;
use ba\Exception;
use think\db\exception\PDOException;
use think\exception\ValidateException;

class AccountClassHourService extends ApiService
{

    //冻结学员课时
    public function studentFrozen($student, $classHourType, $classHourNum)
    {
        if (empty($student)) {
            $this->setError('学员不存在');
            return false;
        }
        try {
            $studentId = $student['id'];
            $coreAccountClassHour = new CoreAccountClassHour();
            $accountClassHour = $coreAccountClassHour->getByStudentId($studentId);
            $classMinutes = $coreAccountClassHour->classMinutes($classHourType, $accountClassHour);
            $beforeClassHourNum = $coreAccountClassHour->classMinutesFreeze($classHourType, $accountClassHour);
            $afterClassHourNum = bcadd($beforeClassHourNum, $classHourNum, 0);
            if ($afterClassHourNum > $classMinutes) {
                throw new ValidateException('课时不足');
            }
            $cnt = $coreAccountClassHour->getService()->updateClassHourFrozen($studentId, AccountTypeEnum::STUDENT, $classHourType, $beforeClassHourNum, $afterClassHourNum);
            if (!$cnt) {
                throw new ValidateException('操作繁忙，请稍后重试');
            }
        } catch (Exception|PDOException|ValidateException $e) {
            $this->setError($e->getMessage());
            return false;
        }
        return true;
    }

    //充值学员
    public function rechargeStudent($recharge)
    {
        $studentId = $recharge['studentId'];
        $classHourType = $recharge['classHourType'];
        $student = Student::where(['id' => $studentId])->find();
        if (empty($student)) {
            $this->setError('学员不存在');
            return false;
        }
        $classHourNum = $recharge['classHourNum'];
        $configService = new ConfigService();
        $minBuyStudentNum = $configService->getSysConfigValue('min_buy_student_num') ?? 20;
        if ($classHourNum < $minBuyStudentNum) {
            $this->setError("充值数量不能小于$minBuyStudentNum");
            return false;
        }
        $organizationId = $student['organizationId'];
        $updateChange = [
            'classHourNum' => $recharge['classHourNum'],
            'classHourType' => $classHourType,
            'payerAccountId' => $organizationId,
            'payerAccountType' => $organizationId == 0 ? AccountTypeEnum::PLATFORM : AccountTypeEnum::ORGAN,
            'receiverAccountId' => $studentId,
            'receiverAccountType' => AccountTypeEnum::STUDENT,
            'businessType' => ClassHourBusinessTypeEnum::E2,
            'describe' => '课时数充值',
            'status' => ClassHourStatusEnum::SUCCESS
        ];
        $consumer = [
            'payAmount' => $recharge['payAmount'] ?? 0,
            'payType' => $recharge['payType']
        ];
        $coreClassHourDetail = new CoreClassHourDetail();
        return $coreClassHourDetail->updateAccountChange($updateChange, $consumer);
    }

    //扣除学员课时
    public function deductStudent($deduct)
    {
        $studentId = $deduct['studentId'];
        $classHourType = $deduct['classHourType'];
        $student = Student::where(['id' => $studentId])->find();
        if (empty($student)) {
            $this->setError('学员不存在');
            return false;
        }
        $organizationId = $student['organizationId'];
        $updateChange = [
            'classHourNum' => $deduct['classHourNum'],
            'classHourType' => $classHourType,
            'payerAccountId' => $studentId,
            'payerAccountType' => AccountTypeEnum::STUDENT,
            'payerRealOrganizationId' => $organizationId,
            'receiverAccountId' => 0,
            'receiverAccountType' => AccountTypeEnum::PLATFORM,
            'businessType' => ClassHourBusinessTypeEnum::E4,
            'describe' => '学员课时扣除',
            'memo' => $deduct['memo'],
            'status' => ClassHourStatusEnum::SUCCESS
        ];
        $coreClassHourDetail = new CoreClassHourDetail();
        return $coreClassHourDetail->updateAccountChange($updateChange, []);
    }

    public function studentReleaseFrozen($student, $classHourType, $classHourNum)
    {
        if (empty($student)) {
            $this->setError('学员不存在');
            return false;
        }
        $studentId = $student['id'];
        $coreAccountClassHour = new CoreAccountClassHour();
        $accountClassHour = $coreAccountClassHour->getByStudentId($studentId);
        $beforeClassHourNum = $coreAccountClassHour->classMinutesFreeze($classHourType, $accountClassHour);
        $afterClassHourNum = bcsub($beforeClassHourNum, $classHourNum, 0);
        if ($afterClassHourNum < 0) {
            $afterClassHourNum = 0;
        }
        $cnt = $coreAccountClassHour->getService()->updateClassHourFrozen($studentId, AccountTypeEnum::STUDENT, $classHourType, $beforeClassHourNum, $afterClassHourNum);
        if (!$cnt) {
            $this->setError('操作繁忙，请稍后重试');
            return false;
        }
        return true;
    }


    //扣除机构课时
    public function deductOrgan(array $deduct)
    {
        $organizationId = $deduct['organizationId'];
        $classHourType = $deduct['classHourType'];
        $organization = Organization::where(['id' => $organizationId])->find();
        if (empty($organization)) {
            $this->setError('机构不存在');
            return false;
        }
        $updateChange = [
            'classHourNum' => $deduct['classHourNum'],
            'classHourType' => $classHourType,
            'payerAccountId' => $organizationId,
            'payerAccountType' => AccountTypeEnum::ORGAN,
            'receiverAccountId' => 0,
            'receiverAccountType' => AccountTypeEnum::PLATFORM,
            'businessType' => ClassHourBusinessTypeEnum::E6,
            'describe' => '机构课时扣除',
            'memo' => $deduct['memo'],
            'status' => ClassHourStatusEnum::SUCCESS
        ];
        $coreClassHourDetail = new CoreClassHourDetail();
        return $coreClassHourDetail->updateAccountChange($updateChange, []);
    }

    //充值机构
    public function rechargeOrgan($isOrgan, $recharge)
    {
        $organizationId = $recharge['organizationId'];
        $classHourType = $recharge['classHourType'];
        $organization = Organization::where(['id' => $organizationId])->find();
        if (empty($organization)) {
            $this->setError('机构不存在');
            return false;
        }
        $parentId = $organization['parentId'];
        $updateChange = [
            'classHourNum' => $recharge['classHourNum'],
            'classHourType' => $classHourType,
            'payerAccountId' => $parentId,
            'payerAccountType' => UserConstantsEnum::ORGANIZATION_PARENT_ID == $parentId ? AccountTypeEnum::PLATFORM : AccountTypeEnum::ORGAN,
            'receiverAccountId' => $organizationId,
            'receiverAccountType' => AccountTypeEnum::ORGAN,
            'businessType' => ClassHourBusinessTypeEnum::E1,
            'rechargeType' => $recharge['rechargeType'],
            'describe' => '课时数充值',
            'memo' => $refund['memo'] ?? '',
            'status' => ClassHourStatusEnum::SUCCESS,
        ];
        if ($isOrgan && $updateChange['payerAccountType'] == AccountTypeEnum::PLATFORM) {
            $this->setError('权限不足');
            return false;
        }
        $consumer = [
            'payAmount' => $recharge['payAmount'] ?? 0,
            'payType' => $recharge['payType']
        ];
        $coreClassHourDetail = new CoreClassHourDetail();
        return $coreClassHourDetail->updateAccountChange($updateChange, $consumer);
    }

    //退费机构
    public function refundOrgan($isOrgan, $refund)
    {
        $organizationId = $refund['organizationId'];
        $classHourType = $refund['classHourType'];
        $organization = Organization::where(['id' => $organizationId])->find();
        if (empty($organization)) {
            $this->setError('机构不存在');
            return false;
        }
        $parentId = $organization['parentId'];
        $updateChange = [
            'classHourNum' => $refund['classHourNum'],
            'classHourType' => $classHourType,
            'payerAccountId' => $organizationId,
            'payerAccountType' => AccountTypeEnum::ORGAN,
            'receiverAccountId' => $parentId,
            'receiverAccountType' => UserConstantsEnum::ORGANIZATION_PARENT_ID == $parentId ? AccountTypeEnum::PLATFORM : AccountTypeEnum::ORGAN,
            'businessType' => ClassHourBusinessTypeEnum::E3,
            'describe' => '机构退费',
            'memo' => $refund['memo'] ?? '',
            'status' => ClassHourStatusEnum::SUCCESS,
        ];
        if ($isOrgan && $updateChange['payerAccountType'] == AccountTypeEnum::PLATFORM) {
            $this->setError('权限不足');
            return false;
        }
        $coreClassHourDetail = new CoreClassHourDetail();
        return $coreClassHourDetail->updateAccountChange($updateChange, []);
    }

    public function jgRechargeStudent($recharge)
    {
        $studentId = $recharge['studentId'];
        $classHourType = $recharge['classHourType'];
        $student = Student::where(['id' => $studentId])->find();
        if (empty($student)) {
            $this->setError('学员不存在');
            return false;
        }
        $organizationId = $student['organizationId'];
        $organization = Organization::where(['id' => $organizationId])->find();
        if (empty($organization)) {
            $this->setError('机构不存在');
            return false;
        }
        $updateChange = [];
        $rechargeType = $recharge['rechargeType'];
        $classHourNum = $recharge['classHourNum'];
        $configService = new ConfigService();
        $minBuyStudentNum = $configService->getSysConfigValue('min_buy_student_num') ?? 20;
        if ($classHourNum < $minBuyStudentNum) {
            $this->setError("充值数量不能小于$minBuyStudentNum");
            return false;
        }
        $payAmount = 0;
        $payType = null;
        switch ($rechargeType) {
            case 1:
                $updateChange = [
                    'payerAccountId' => $organizationId,
                    'payerAccountType' => AccountTypeEnum::ORGAN,
                    'status' => ClassHourStatusEnum::SUCCESS
                ];
                break;
            case '2':
                $level = $organization['level'];
                $organizationLevelConfig = new OrganizationLevelConfig();
                $levelConfig = $organizationLevelConfig->where(['id' => $level])->find();
                if (empty($levelConfig)) {
                    $this->setError('机构等级不存在');
                    return false;
                }
                if (!$levelConfig['rechargeOnlineStudent']) {
                    $this->setError('暂不支持线上充值');
                    return false;
                }
                $price = $organizationLevelConfig->classHourAmount($levelConfig, $classHourType);
                $payAmount = bcmul($classHourNum, $price);
                $payType = $recharge['payType'] ?? null;
                if (empty($payType)) {
                    $this->setError('请选择支付方式');
                    return false;
                }
                $updateChange = [
                    'payerAccountId' => "0",
                    'payerAccountType' => AccountTypeEnum::PLATFORM,
                    'payerRealOrganizationId' => $organizationId,
                    'status' => ClassHourStatusEnum::IN
                ];
                break;
        }

        $updateChange['classHourNum'] = $classHourNum;
        $updateChange['classHourType'] = $classHourType;
        $updateChange['receiverAccountId'] = $studentId;
        $updateChange['receiverAccountType'] = AccountTypeEnum::STUDENT;
        $updateChange['businessType'] = ClassHourBusinessTypeEnum::E2;
        $updateChange['describe'] = "机构为【{$student['name']}】课时数充值";
        $finalPayAmount = $payAmount;
        $finalPayType = $payType;
        $consumer = [
            'payAmount' => $finalPayAmount,
            'payType' => $finalPayType
        ];
        if ($rechargeType == '2') {
            $consumer['isLinePay'] = 1;
        }
        $coreClassHourDetail = new CoreClassHourDetail();
        $res = $coreClassHourDetail->updateAccountChange($updateChange, $consumer);
        $rwId = $res['id'];
        $payParams = null;
        if ($rechargeType == '2') {
            $this->setError('暂不支持该支付方式');
            return false;
            switch ($payType) {
                case PayTypeEnum::WECHAT:
                    $wxPayService = new WxPayService();
                    $time_expire = date('Y-m-d H:i:s', strtotime('+30 minute'));
                    $payParams = $wxPayService->nativePay(
                        '学员课时购买',
                        null,
                        $rwId,
                        $finalPayAmount,
                        '/common_api/core/coreAccountClassHour/payCallWechat',
                        $time_expire
                    );
                    $qrcodeService = new QrcodeService();
                    $payParams = $qrcodeService->generate(
                        $payParams,
                        ['width' => 200, 'height' => 200]
                    );
                    break;
                case PayTypeEnum::ALIPAY:
                    $alipayService = new AlipayService();
                    $payParams = $alipayService->scanCodePay(
                        $rwId,
                        $finalPayAmount,
                        '学员课时购买',
                        '/common_api/core/coreAccountClassHour/payCallAlipay'
                    );
                    $qrcodeService = new QrcodeService();
                    $payParams = $qrcodeService->generate(
                        $payParams,
                        ['width' => 200, 'height' => 200]
                    );
                    break;
                default:
                    $this->setError('暂不支持该支付方式');
                    return false;
            }
        }
        return [
            'orderId' => $rwId,
            'payType' => $payType,
            'payParams' => $payParams
        ];
    }

    public function payCall($orderId, $payAmount, $payNumber, $payType)
    {
        $coreClassHourDetail = new CoreClassHourDetail();
        $orderInfo = $coreClassHourDetail->where(['id' => $orderId])->find();
        if (empty($orderInfo)) {
            logSave([
                'msg' => '订单回调支付警告，订单不存在',
                'orderId' => $orderId,
                'payAmount' => $payAmount,
                'payNumber' => $payNumber,
                'payType' => $payType,
            ], 'payCall', 'accountClassHourService');
            return true;
        }
        $state = $orderInfo['status'];
        if ($state == ClassHourStatusEnum::SUCCESS) {
            logSave([
                'msg' => '订单回调支付警告，订单已支付',
                'orderId' => $orderId,
                'payAmount' => $payAmount,
                'payNumber' => $payNumber,
                'payType' => $payType,
            ], 'payCall', 'accountClassHourService');
            return true;
        }
        if (!$orderInfo['getIsLinePay']) {
            logSave([
                'msg' => '订单回调支付警告，订单非线上支付订单',
                'orderId' => $orderId,
                'payAmount' => $payAmount,
                'payNumber' => $payNumber,
                'payType' => $payType,
            ], 'payCall', 'accountClassHourService');
            return true;
        }
        if ($state == ClassHourStatusEnum::CANCEL || $state == ClassHourStatusEnum::FAIL) {
            logSave([
                'msg' => '订单回调支付警告，订单状态异常',
                'status' => $state,
                'orderId' => $orderId,
                'payAmount' => $payAmount,
                'payNumber' => $payNumber,
                'payType' => $payType,
            ], 'payCall', 'accountClassHourService');
            return true;
        }
        $amount = $orderInfo['payAmount'];
        if ($amount != null && bccomp($amount, $payAmount, 2) !== 0) {
            logSave([
                'msg' => '订单回调支付警告，订单金额不匹配',
                'money' => $amount,
                'callMoney' => $payAmount,
                'orderId' => $orderId,
                'payAmount' => $payAmount,
                'payNumber' => $payNumber,
                'payType' => $payType,
            ], 'payCall', 'accountClassHourService');
            return true;
        }
        $cnt = $coreClassHourDetail->where(['id' => $orderId, 'status' => $state])->update([
            'payType' => $payType,
            'payNo' => $payNumber,
            'payTime' => date('Y-m-d H:i:s'),
            'status' => ClassHourStatusEnum::SUCCESS
        ]);
        if (!$cnt) {
            logSave([
                'orderId' => $orderId,
                'payAmount' => $payAmount,
                'payNumber' => $payNumber,
                'payType' => $payType,
                'orderInfo' => json_encode($orderInfo, true),
                'message' => '订单回调支付警告，订单修改支付状态失败'
            ], 'payCall', 'accountClassHourService');
        }
        //入账
        $coreClassHourDetail->updateInAccount($orderInfo);
        return true;
    }
}

